package com.youxin.chat.pay.service.channel.impl.ypl;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.youxin.base.BaseResultCode;
import com.youxin.chat.pay.enums.CashStatusEnum;
import com.youxin.chat.pay.enums.OrderStatusEnum;
import com.youxin.chat.pay.model.ChannelAccount;
import com.youxin.chat.pay.model.ChannelOrder;
import com.youxin.chat.pay.model.UserCash;
import com.youxin.chat.pay.model.UserRecharge;
import com.youxin.chat.pay.service.channel.IPayChannel;
import com.youxin.chat.pay.enums.PayChannelEnum;
import com.youxin.chat.pay.service.channel.entity.*;
import com.youxin.chat.pay.service.channel.impl.ypl.convert.YplErrorTransfer;
import com.youxin.chat.pay.service.channel.impl.ypl.request.*;
import com.youxin.chat.pay.service.channel.impl.ypl.util.YplHttpUtil;
import com.youxin.chat.pay.service.channel.impl.ypl.util.YplSignUtil;
import com.youxin.chat.pay.utils.ParamStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class YplPayChannel implements IPayChannel {
    private static final Logger logger = LoggerFactory.getLogger(YplPayChannel.class);

    @Resource
    private StringRedisTemplate stringRedisTemplate;



    @Override
    public ChannelResponse bindCard(String orderNo, ChannelBindCard channelBindCard, ChannelAccount channelAccount) {
        ChannelResponse response = new ChannelResponse(BaseResultCode.SUCCESS);
        JSONObject jsonObject = YplBindCard.auditBindCardRequest(orderNo, channelBindCard, channelAccount);
        String content = ParamStringUtils.toSignStr(jsonObject, "signMsg", "|");
        String signMsg = YplSignUtil.buildSign(JSONObject.toJSONString(jsonObject), channelAccount.getRsaKeyPri());
        Map<String, String> headers = new HashMap<>();
        headers.put("x-efps-sign-no", JSONObject.parseObject(channelAccount.getExtInfo()).getString("signNo"));
        headers.put("x-efps-sign-type", "SHA256withRSA");
        headers.put("x-efps-sign", signMsg);
        headers.put("x-efps-timestamp", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
        String result;
        try {
            String url = channelAccount.getChannelUrl() + "/api/txs/protocol/bindCard";
            result = YplHttpUtil.getHttpPost(url, headers, JSONObject.toJSONString(jsonObject), channelAccount.getRsaKeyPub());
            logger.info("auditBindCard,{}", "联通绑卡回调数据:" + result);
            JSONObject object = JSONObject.parseObject(result);
            if ("0000".equalsIgnoreCase(object.getString("returnCode"))) {
                response.setCode(BaseResultCode.SUCCESS);
                response.setStatus(1);
                response.setResult(result);
                response.setExt(object.getString("smsNo"));
            } else {
                response = YplErrorTransfer.buildErrorResult(object.getString("returnCode"), object.getString("returnMsg"));
                logger.error("请求绑卡接口失败:" + object.getString("returnMsg"));
                return response;
            }
        } catch (Exception e) {
            logger.error("请求绑卡接口失败:", e);
            response.setCode(BaseResultCode.COMMON_FAIL);
            response.setErrorMsg("请求绑卡接口失败");
            return response;
        }
        response.setResult(result);

        return response;
    }

    @Override
    public ChannelResponse validateSms(ChannelBindCardSms channelBindCardSms, ChannelAccount channelAccount) {
        ChannelResponse response = new ChannelResponse(BaseResultCode.SUCCESS);
        JSONObject jsonObject = YplBindCard.validateBindSmsRequest(channelBindCardSms, channelAccount);
        String content = ParamStringUtils.toSignStr(jsonObject, "signMsg", "|");
        String signMsg = YplSignUtil.buildSign(JSONObject.toJSONString(jsonObject), channelAccount.getRsaKeyPri());
        Map<String, String> headers = new HashMap<>();
        headers.put("x-efps-sign-no", JSONObject.parseObject(channelAccount.getExtInfo()).getString("signNo"));
        headers.put("x-efps-sign-type", "SHA256withRSA");
        headers.put("x-efps-sign", signMsg);
        headers.put("x-efps-timestamp", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
        String result;
        try {
            String url = channelAccount.getChannelUrl() + "/api/txs/protocol/bindCardConfirm";
            result = YplHttpUtil.getHttpPost(url, headers, JSONObject.toJSONString(jsonObject), channelAccount.getRsaKeyPub());
            logger.info("validateSms,{}", "联通绑卡短信回调数据:" + result);
            JSONObject object = JSONObject.parseObject(result);

            if ("0000".equalsIgnoreCase(object.getString("returnCode"))) {
                response.setCode(BaseResultCode.SUCCESS);
                response.setStatus(1);
                response.setResult(result);
                response.setAgreementId(object.getString("protocol"));
            } else {
                response = YplErrorTransfer.buildErrorResult(object.getString("returnCode"), object.getString("returnMsg"));
                response.setResult(result);
            }
        } catch (Exception e) {
            logger.error("签约短信验证失败:", e);
            response.setCode(BaseResultCode.COMMON_FAIL);
            response.setErrorMsg("请求接口异常");
            return response;
        }

        return response;
    }

    @Override
    public boolean support(String channelCode) {
        return PayChannelEnum.YPL.getChannelCode().equalsIgnoreCase(channelCode);
    }

    @Override
    public ChannelResponse pay(ChannelPay channelPay, ChannelAccount channelAccount) {
        ChannelResponse response = new ChannelResponse(BaseResultCode.SUCCESS);

        JSONObject jsonObject = YplPay.buildPayRequest(channelPay, channelAccount);
        String sign = YplSignUtil.buildSign(JSONObject.toJSONString(jsonObject), channelAccount.getRsaKeyPri());

        Map<String, String> headers = new HashMap<>();
        headers.put("x-efps-sign-no", JSONObject.parseObject(channelAccount.getExtInfo()).getString("signNo"));
        headers.put("x-efps-sign-type", "SHA256withRSA");
        headers.put("x-efps-sign", sign);
        headers.put("x-efps-timestamp", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
        String result;
        try {
            String url = channelAccount.getChannelUrl() + "/api/txs/protocol/protocolPayPre";
            result = YplHttpUtil.getHttpPost(url, headers, JSONObject.toJSONString(jsonObject), channelAccount.getRsaKeyPub());
            logger.info("pay,{}", "YPL支付回调数据:" + result);

            JSONObject object = JSONObject.parseObject(result);
            if ("0000".equalsIgnoreCase(object.getString("returnCode"))) {

                Map<String, String> dataMap = new HashMap<>();
                dataMap.put("token", object.getString("token"));
                dataMap.put("protocol", channelPay.getContractId());
                dataMap.put("memberId", channelPay.getUserNo());
                dataMap.put("customerCode", channelAccount.getChannelAccount());

                response.setCode(BaseResultCode.SUCCESS);
                response.setStatus(1);
                response.setResult(result);
                response.setExt(JSONObject.toJSONString(dataMap));
            } else {
                response = YplErrorTransfer.buildErrorResult(object.getString("returnCode"), object.getString("returnMsg"));
                response.setResult(result);
            }

        } catch (Exception e) {
            logger.error("请求支付接口失败:", e);
            response.setErrorMsg("请求支付接口失败:");
            return response;
        }

        return response;
    }

    @Override
    public ChannelResponse termination(ChannelTerminationCard channelTerminationCard, ChannelAccount channelAccount) {
        ChannelResponse response = new ChannelResponse(BaseResultCode.SUCCESS);

        JSONObject jsonObject = YplTermination.buildTerminationRequest(channelTerminationCard);
        String sign = YplSignUtil.buildSign(JSONObject.toJSONString(jsonObject), channelAccount.getRsaKeyPri());

        Map<String, String> headers = new HashMap<>();
        headers.put("x-efps-sign-no", JSONObject.parseObject(channelAccount.getExtInfo()).getString("signNo"));
        headers.put("x-efps-sign-type", "SHA256withRSA");
        headers.put("x-efps-sign", sign);
        headers.put("x-efps-timestamp", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
        String result;
        try {
            String url = channelAccount.getChannelUrl() + "/api/txs/protocol/unBindCard";
            result = YplHttpUtil.getHttpPost(url, headers, JSONObject.toJSONString(jsonObject), channelAccount.getRsaKeyPub());
            logger.info("termination,{}", "YPL解绑回调数据:" + result);

            JSONObject object = JSONObject.parseObject(result);
            if ("0000".equalsIgnoreCase(object.getString("returnCode"))) {
                response.setCode(BaseResultCode.SUCCESS);
                response.setStatus(1);
                response.setResult(result);
            } else {
                response = YplErrorTransfer.buildErrorResult(object.getString("returnCode"), object.getString("returnMsg"));
                response.setResult(result);
            }

        } catch (Exception e) {
            logger.error("请求支付接口失败:", e);
            response.setErrorMsg("请求支付接口失败:");
            return response;
        }

        return response;
    }

    @Override
    public ChannelNotifyResponse orderNotify(ChannelNotifyRequest request, ChannelAccount channelAccount) {
        ChannelNotifyResponse response = new ChannelNotifyResponse();
        response.setOrderNo(request.getOrderNo());
        response.setStatus(OrderStatusEnum.NOT_PAY.getStatus());
        logger.info("YplPay:orderNotify,{}", "收到易票联回调请求:" + JSONObject.toJSONString(request));

        Map<String, String> resultMap = new HashMap<>();
        resultMap.put("returnCode", "0000");
        ObjectMapper mapper = new ObjectMapper();
        String sign = request.getExt();

        boolean flag = YplSignUtil.verify(request.getData(), channelAccount.getRsaKeyPub(), sign);
        if (!Boolean.TRUE.equals(flag)) {
            resultMap.put("returnCode", "0001");
            response.setResponseText(JSONObject.toJSONString(resultMap));
        }
        logger.info("YplPay:orderNotify,{}", "收到易票联回调验签成功");
        try {
            JSONObject jsonObject = JSONObject.parseObject(request.getData());
            String code = (String) jsonObject.getString("payState");
            if ("00".equalsIgnoreCase(code)) {
                response.setStatus(OrderStatusEnum.PAY_SUCCESS.getStatus());
                response.setResponseText(JSONObject.toJSONString(resultMap));
                return response;
            } else if ("01".equalsIgnoreCase(code)) {
                response.setStatus(OrderStatusEnum.PAY_FAIL.getStatus());
                response.setResponseText(JSONObject.toJSONString(resultMap));
                return response;
            }

        } catch (Exception e) {
            resultMap.put("returnCode", "0001");
            response.setResponseText(JSONObject.toJSONString(resultMap));
            return response;
        }
        response.setResponseText(JSONObject.toJSONString(resultMap));

        return response;
    }

    @Override
    public ChannelNotifyResponse defrayNotify(ChannelNotifyRequest request, ChannelAccount channelAccount) {
        ChannelNotifyResponse response = new ChannelNotifyResponse();
        response.setOrderNo(request.getOrderNo());
        response.setStatus(OrderStatusEnum.NOT_PAY.getStatus());
        logger.info("YplDefray:defrayNotify,{}", "收到易票联代付回调请求:" + JSONObject.toJSONString(request));

        Map<String, String> resultMap = new HashMap<>();
        resultMap.put("returnCode", "0000");
        ObjectMapper mapper = new ObjectMapper();
        String sign = request.getExt();

        boolean flag = YplSignUtil.verify(request.getData(), channelAccount.getRsaKeyPub(), sign);
        if (!Boolean.TRUE.equals(flag)) {
            resultMap.put("returnCode", "0001");
            response.setResponseText(JSONObject.toJSONString(resultMap));
        }
        logger.info("YplPay:defrayNotify,{}", "收到易票联代付回调验签成功");
        try {
            JSONObject jsonObject = JSONObject.parseObject(request.getData());
            String code = (String) jsonObject.getString("payState");
            if ("00".equalsIgnoreCase(code)) {
                response.setStatus(OrderStatusEnum.PAY_SUCCESS.getStatus());
                response.setResponseText(JSONObject.toJSONString(resultMap));
                return response;
            } else if ("01".equalsIgnoreCase(code)) {
                response.setStatus(OrderStatusEnum.PAY_FAIL.getStatus());
                response.setResponseText(JSONObject.toJSONString(resultMap));
                return response;
            }

        } catch (Exception e) {
            resultMap.put("returnCode", "0001");
            response.setResponseText(JSONObject.toJSONString(resultMap));
            return response;
        }
        response.setResponseText(JSONObject.toJSONString(resultMap));

        return response;
    }

    @Override
    public ChannelResponse payQuery(ChannelOrder channelOrder, ChannelAccount channelAccount) {
        return null;
    }

    @Override
    public ChannelResponse defray(ChannelDefray channelDefray, ChannelAccount channelAccount) {
        ChannelResponse response = new ChannelResponse(BaseResultCode.SUCCESS);
        JSONObject jsonObject = YplDefray.buildDefrayRequest(channelDefray, channelAccount);
        String sign = YplSignUtil.buildSign(JSONObject.toJSONString(jsonObject), channelAccount.getRsaKeyPri());

        Map<String, String> headers = new HashMap<>();
        headers.put("x-efps-sign-no", JSONObject.parseObject(channelAccount.getExtInfo()).getString("signNo"));
        headers.put("x-efps-sign-type", "SHA256withRSA");
        headers.put("x-efps-sign", sign);
        headers.put("x-efps-timestamp", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
        String result;
        try {
            String url = channelAccount.getChannelUrl() + "/api/txs/pay/withdrawalToCard";
            result = YplHttpUtil.getHttpPost(url, headers, JSONObject.toJSONString(jsonObject), channelAccount.getRsaKeyPub());
            logger.info("defray,{}", "YPL代付回调数据:" + result);

            JSONObject object = JSONObject.parseObject(result);
            if ("0000".equalsIgnoreCase(object.getString("returnCode"))) {
                response.setCode(BaseResultCode.SUCCESS);
                response.setStatus(1);
                response.setResult(result);
            } else {
                response = YplErrorTransfer.buildErrorResult(object.getString("returnCode"), object.getString("returnMsg"));
                response.setResult(result);
            }

        } catch (Exception e) {
            logger.error("请求代付接口失败:", e);
            response.setErrorMsg("请求代付接口失败:");
            return response;
        }

        return response;
    }

    @Override
    public ChannelResponse defrayQuery(UserCash userCash, ChannelAccount channelAccount) {
        ChannelResponse response = new ChannelResponse(BaseResultCode.SUCCESS);

        JSONObject jsonObject = YplDefray.buildDefrayQueryRequest(userCash, channelAccount);
        String sign = YplSignUtil.buildSign(JSONObject.toJSONString(jsonObject), channelAccount.getRsaKeyPri());

        Map<String, String> headers = new HashMap<>();
        headers.put("x-efps-sign-no", JSONObject.parseObject(channelAccount.getExtInfo()).getString("signNo"));
        headers.put("x-efps-sign-type", "SHA256withRSA");
        headers.put("x-efps-sign", sign);
        headers.put("x-efps-timestamp", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
        String result;
        try {
            String url = channelAccount.getChannelUrl() + "/api/txs/pay/withdrawalToCardQuery";
            result = YplHttpUtil.getHttpPost(url, headers, JSONObject.toJSONString(jsonObject), channelAccount.getRsaKeyPub());
            logger.info("defrayQuery,{}", "YPL代付结果回调数据:" + result);

            JSONObject object = JSONObject.parseObject(result);
            if ("0000".equalsIgnoreCase(object.getString("returnCode"))) {
                if ("00".equalsIgnoreCase(object.getString("payState"))) {
                    response.setCode(BaseResultCode.SUCCESS);
                    response.setStatus(CashStatusEnum.SUCCESS.getStatus());
                    response.setResult(result);
                } else if ("01".equalsIgnoreCase(object.getString("payState"))) {
                    response.setCode(BaseResultCode.SUCCESS);
                    response.setStatus(CashStatusEnum.FAIL.getStatus());
                    response.setResult(result);
                }
            } else {
                response.setCode(BaseResultCode.COMMON_FAIL);
                response.setResult(result);
            }

        } catch (Exception e) {
            logger.error("请求支付接口失败:", e);
            response.setErrorMsg("请求支付接口失败:");
            return response;
        }

        return response;
    }

    @Override
    public ChannelResponse doChargeSms(ChannelChargeSms channelChargeSms, ChannelAccount channelAccount) {
        ChannelResponse response = new ChannelResponse(BaseResultCode.SUCCESS);

        JSONObject jsonObject = YplPay.doChargeSmsRequest(channelChargeSms);
        logger.info("doChargeSms,{}", "YPL支付短信请求数据:" + jsonObject.toJSONString());

        String signMsg = YplSignUtil.buildSign(JSONObject.toJSONString(jsonObject), channelAccount.getRsaKeyPri());
        Map<String, String> headers = new HashMap<>();
        headers.put("x-efps-sign-no", JSONObject.parseObject(channelAccount.getExtInfo()).getString("signNo"));
        headers.put("x-efps-sign-type", "SHA256withRSA");
        headers.put("x-efps-sign", signMsg);
        headers.put("x-efps-timestamp", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
        String result;
        try {
            String url = channelAccount.getChannelUrl() + "/api/txs/protocol/protocolPayConfirm";
            result = YplHttpUtil.getHttpPost(url, headers, JSONObject.toJSONString(jsonObject), channelAccount.getRsaKeyPub());
            logger.info("doChargeSms,{}", "YPL支付短信确认回调:" + result);
            JSONObject object = JSONObject.parseObject(result);

            if ("0000".equalsIgnoreCase(object.getString("returnCode"))) {
                response.setStatus(1);
                response.setCode(BaseResultCode.SUCCESS);
                response.setResult(result);
            } else {
                response = YplErrorTransfer.buildErrorResult(object.getString("returnCode"), object.getString("returnMsg"));
                response.setResult(result);
            }
        } catch (Exception e) {
            logger.error("确认支付验证失败:", e);
            response.setCode(BaseResultCode.COMMON_FAIL);
            response.setErrorMsg("请求接口异常");
            return response;
        }

        return response;
    }

    @Override
    public ChannelResponse balanceQuery(ChannelAccount channelAccount) {
        ChannelResponse response = new ChannelResponse(BaseResultCode.SUCCESS);

        JSONObject jsonObject = YplBalance.buildBalanceRequest(channelAccount);
        logger.info("balanceQuery,{}", "YPL余额查询请求数据:" + jsonObject.toJSONString());

        String signMsg = YplSignUtil.buildSign(JSONObject.toJSONString(jsonObject), channelAccount.getRsaKeyPri());
        Map<String, String> headers = new HashMap<>();
        headers.put("x-efps-sign-no", JSONObject.parseObject(channelAccount.getExtInfo()).getString("signNo"));
        headers.put("x-efps-sign-type", "SHA256withRSA");
        headers.put("x-efps-sign", signMsg);
        headers.put("x-efps-timestamp", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
        String result;
        try {
            String url = channelAccount.getChannelUrl() + "/api/acc/accountQuery";
            result = YplHttpUtil.getHttpPost(url, headers, JSONObject.toJSONString(jsonObject), channelAccount.getRsaKeyPub());
            logger.info("balanceQuery,{}", "YPL余额查询回调:" + result);
            JSONObject object = JSONObject.parseObject(result);

            if ("0000".equalsIgnoreCase(object.getString("returnCode"))) {
                response.setStatus(1);
                response.setCode(BaseResultCode.SUCCESS);
                response.setResult(result);
                Map<String, BigDecimal> map = new HashMap();
                map.put("balance", new BigDecimal(object.getString("availableBalance")).add(new BigDecimal(object.getString("floatBalance"))));
                map.put("availableBalance", new BigDecimal(object.getString("availableBalance")));
                map.put("lockAmount", new BigDecimal(object.getString("floatBalance")));
                String ext = JSONObject.toJSONString(map);
                response.setExt(ext);
            } else {
                response = YplErrorTransfer.buildErrorResult(object.getString("returnCode"), object.getString("returnMsg"));
                response.setResult(result);
            }
        } catch (Exception e) {
            logger.error("余额查询失败:", e);
            response.setCode(BaseResultCode.COMMON_FAIL);
            response.setErrorMsg("请求接口异常");
            return response;
        }

        return response;
    }


}
